package com.apes.scm.account.tax.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.LogicalUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.PurchaseTax;
import com.apes.scm.account.tax.model.SaleTax;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.repository.PurchaseTaxRepository;
import com.apes.scm.account.tax.repository.SaleTaxRepository;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.multiKeys.CompanyProduct;
import com.apes.scm.masterdata.multiKeys.SupplierProduct;
import com.apes.scm.masterdata.party.model.Corporate;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.party.service.PartyRoleService;
import com.apes.scm.masterdata.party.service.SupplierService;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 功能：税率相关服务
 *
 * @author xul
 * @create 2018-02-03 16:10
 */
@Service("taxService")
public class TaxService extends DomainService {

    @Autowired
    TaxRepository taxRepository;

    @Autowired
    SaleTaxRepository saleTaxRepository;

    @Autowired
    PurchaseTaxRepository purchaseTaxRepository;

    public Tax create(SimpleRequest request) {
        Tax tax = request.getO(Tax.class);
        return taxRepository.saveAndFlush(tax);
    }


    /**
     * 功能：查询所有税别
     *
     * @param request
     */
    public Page<Tax> findAll(SimpleRequest request) {
        List<Map> filters = request.get("condition");
        if (filters.size() > 0) {
            String id = filters.get(0).get("value").toString();
            Pattern pattern = Pattern.compile("[0-9]*");
            Matcher isNum = pattern.matcher(id);
            if (!isNum.matches()) {
                //throw new RuntimeException("输入非数字编码");
            } else {
                // filters.get(0).put("value",Long.parseLong(filters.get(0).get("value").toString()));
            }
        }
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        return taxRepository.findAll(JpaDsl.toCriteria(filters), PageRequest.of(request.get("page"), request.get("size"), sort));
    }

    public Tax save(Tax tax) {
        return taxRepository.saveAndFlush(tax);
    }

    public String delete(SimpleRequest request) throws Exception {

        String id = request.get("id");
        long versions = (Long) request.get("version");

        Tax tax = taxRepository.findOne(Long.valueOf(id));
        if (tax == null) throw new RuntimeException("稅別【" + id + "】在系统中不存在。");
        if (tax.getVersion() != versions) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        taxRepository.delete(tax);
        return "删除成功";
    }

    public Tax findOne(long id) {
        return taxRepository.findOne(id);
    }


    public Page<Tax> findByValid(SimpleRequest request) {
        return taxRepository.findByValid(true, PageRequest.of(request.get("page"), request.get("size")));
    }

    /*
     * 功能：公司商品销项税
     */
    public Tax getSaleTax(PartyRole company, Product product) {
        CompanyProduct keysClass = new CompanyProduct(company.getId(), product.getId());
        SaleTax saleTax = saleTaxRepository.findOne(keysClass);
        if (saleTax != null) return saleTax.getTax();

        if ("02".equals(getTaxpayerCode(company))) { /**小规模纳税人**/
            List<Object> businessParam = sendSynEvent("event:businessParam.findOne", MapUtil.mapper("id", "16"));
            if (businessParam == null || businessParam.size() == 0) throw new RuntimeException("没有配置小规模纳税人税率参数 ！");

            String taxId;
            if (isMemberProduct(product)) { // 余额商品  taxId 5   无税
                taxId = ReflectUtil.getFieldValue(businessParam.get(0), "value2");
            } else { // 非余额商品 taxId 2  3%增值税
               taxId = ReflectUtil.getFieldValue(businessParam.get(0), "value");
            }
            if (StringUtils.isEmpty(taxId)) throw new RuntimeException("小规模纳税人税率参数配置错误 ！");

            Tax tax = taxRepository.findOne(Long.valueOf(taxId));
            if (tax == null) throw new RuntimeException("没有找到对应的税率记录，税率编码为：" + taxId);
            return tax;
        } else { /**一般纳税人**/
            if (product.getTax() != null) return product.getTax();
            Tax tax = company.getParty().getCorporate().getTax();
            if (tax != null) {
                return tax;
            }
        }
        throw new RuntimeException(String.format("公司：%s [%s] 未定义销项税！", company.getParty().getId(), company.getParty().getName()));
    }

    /**
     * 判断是否是会员商品
     **/
    private boolean isMemberProduct(Product product) {
        return LogicalUtil.in(product.getProductGroup().getId(), "60", "70");
    }

    /*
     * 功能：供应商商品进项税
     */
    public Tax getPurchaseTax(PartyRole supplier, Product product) {
        if (supplier.getParty().getCorporate().inner()) { /**内部供应商**/
            PartyRole company = getCompany(supplier);

            /* 判断供应商是否为小规模纳税人 */
            if ("02".equals(getTaxpayerCode(company))) {
                Tax tax = taxRepository.findOne(5l);
                if (tax == null) throw new RuntimeException("没有找到对应的税率记录，税率编码为：5");
                return tax;
            }

            return getSaleTax(company, product);
        } else { /**外部供应商**/
            SupplierProduct keysClass = new SupplierProduct(supplier.getId(), product.getId());
            PurchaseTax purchaseTax = purchaseTaxRepository.findOne(keysClass);
            if (purchaseTax != null) return purchaseTax.getTax();
            Tax tax = supplier.getParty().getCorporate().getTax();
            if (tax != null) {
                return tax;
            }
        }

        throw new RuntimeException(String.format("供应商：%s [%s] 未定义进项税！", supplier.getParty().getId(), supplier.getParty().getName()));
    }

    /**
     * 根据公司获取对应的小规模纳税人枚举值 code
     *
     * @param company 公司
     * @return taxpayer Code（02 为 小规模纳税人，01 为 一般纳税人）
     */
    private String getTaxpayerCode(PartyRole company) {
        Corporate corporate = company.getParty().getCorporate();
        Optional.ofNullable(corporate).orElseThrow(() -> new RuntimeException(String.format("未定义公司或供应商【%s】的财务信息，请检查！", company.getId())));
        Optional.ofNullable(corporate.getTaxpayer()).orElseThrow(() -> new RuntimeException(String.format("未定义公司或供应商【%s】的纳税人信息，请检查！", company.getId())));
        return corporate.getTaxpayer().getCode();
    }

    /**
     * 小规模纳税人新增获取税率
     * <ol>
     *     <li>小规模纳税人 找 一般纳税人 采购，进项税为 0</li>
     *     <li>一般纳税人 找 小规模纳税人 采购，进项税为 0</li>
     *     <li>一般纳税人 找 一般纳税人 采购，进项税为 上游销项税</li>
     * </ol>
     *
     * @param company  当前公司
     * @param supplier 供应商
     * @param product  商品
     * @return Tax
     */
    public Tax getPurchaseTax(PartyRole company, PartyRole supplier, Product product) {
        /* 第一步：判断是否为小规模纳税人采购 */
        if ("02".equals(getTaxpayerCode(company))) {
            Tax tax = taxRepository.findOne(5l);    // taxId 为 5, 进项税率为 0
            if (tax == null) throw new RuntimeException("没有找到对应的税率记录，税率编码为：5");
            return tax;
        }

        // 第二步：获取上游的销项税
        return getPurchaseTax(supplier, product);
    }

    protected PartyRole getCompany(PartyRole owner) {
        owner = SpringManager.getBean(PartyRoleRepository.class).findOne(owner.getId());
        PartyRole company = SpringManager.getBean(PartyRoleService.class).findByPartyAndRole(owner.getParty().getId(), "Company");
        if (company == null) throw new RuntimeException("内部公司：" + owner.getName() + " 没有定义公司角色！");
        return company;
    }

    public Tax getPurchaseTax1(SimpleRequest request) {
        PartyRole supplier = getBean(SupplierService.class).findOne(request.get("supplierId"));
        Product product = getBean(ProductService.class).findOne(request.get("productId"));
        return getPurchaseTax(supplier, product);
    }

    /**
     * 功能：计算税金
     */
    public Map computeTaxAmount(SimpleRequest request) {
        PartyRole company = getBean(PartyRoleService.class).findOne(request.get("companyId"), "Company");
        if (company == null) throw new RuntimeException("公司：" + request.get("companyId") + " 未定义！");
        Tax tax = findOne(request.get("taxId"));
        if (tax == null) throw new RuntimeException("税：" + request.get("taxId") + " 未定义！");
        return tax.computeAll(company, Double.valueOf(request.get("priceUnit")), Double.valueOf(request.get("qty")));
    }
}
